package edu.hawaii.myisern.xml;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;

import edu.hawaii.myisern.collaborations.jaxb.Collaborations;
import edu.hawaii.myisern.organizations.jaxb.Organizations;
import edu.hawaii.myisern.researchers.jaxb.Researchers;

/**
 * Provides sample code for loading XML and marshalling it into their JAXB related classes.
 * 
 * @author Philip Johnson edited by Ivan Wu, Chiao-Fen Zielinski-Liu, and Michal Zielinski.
 */
public class MyIsernXmlLoader {

  /** Holds the class-wide JAXBContext, which is thread-safe. */
  private JAXBContext collaborationsJaxbContext;
  /** Holds the class-wide JAXBContext, which is thread-safe. */
  private JAXBContext organizationsJaxbContext;
  /** Holds the class-wide JAXBContext, which is thread-safe. */
  private JAXBContext researchersJaxbContext;
  /** Holds. */
  public Collaborations collaborations;
  /** Holds. */
  public Organizations organizations;
  /** Holds. */
  public Researchers researchers;
  
  private String jaxbCollabContextString = "edu.hawaii.myisern.collaborations.jaxb";
  private String jaxbOrgContextString = "edu.hawaii.myisern.organizations.jaxb";
  private String jaxbResearcherContextString = "edu.hawaii.myisern.researchers.jaxb";
	
  /** Default file location for researcher xml 
   * @param researcherXmlPath path of the xml file.
   * @param organizationXmlPath path of the xml file.
   * @param collaborationXmlPath path of the xml file.
   * @throws JAXBException if error occurs. 
   * 
   */
  public MyIsernXmlLoader(String researcherXmlPath, 
		                  String organizationXmlPath, 
                          String collaborationXmlPath) throws JAXBException {
      
	// Load in the Collaborations XML example file.
    this.collaborationsJaxbContext = JAXBContext.newInstance(jaxbCollabContextString);
    File collaborationsFile = new File(collaborationXmlPath);
    Unmarshaller unmarshaller = this.collaborationsJaxbContext.createUnmarshaller();
    this.collaborations = (Collaborations) unmarshaller.unmarshal(collaborationsFile);

    // Do the same for organizations.
    this.organizationsJaxbContext = JAXBContext.newInstance(jaxbOrgContextString);
    File organizationsFile = new File(organizationXmlPath);
    unmarshaller = this.organizationsJaxbContext.createUnmarshaller();
    this.organizations = (Organizations) unmarshaller.unmarshal(organizationsFile);

    // Now do it once more for the researchers.
    this.researchersJaxbContext = JAXBContext.newInstance(jaxbResearcherContextString);
    File researchersFile = new File(researcherXmlPath);
    unmarshaller = this.researchersJaxbContext.createUnmarshaller();
    this.researchers = (Researchers) unmarshaller.unmarshal(researchersFile);
  }

  /**
   * Initializes this instance by reading in the three example XML files.
   * 
   * @throws Exception If problems occur.
   */
  public MyIsernXmlLoader() throws Exception {
    String cwd = System.getProperty("user.home");
    String collabXml = "/.myisern/collaborations.xml";
    String orgXml = "/.myisern/organizations.xml";
    String researcherXml = "/.myisern/researchers.xml";

	  
    // Load in the Collaborations XML example file.
    this.collaborationsJaxbContext = JAXBContext.newInstance(jaxbCollabContextString);
    File collaborationsFile = new File(cwd + collabXml);
    Unmarshaller unmarshaller = this.collaborationsJaxbContext.createUnmarshaller();
    this.collaborations = (Collaborations) unmarshaller.unmarshal(collaborationsFile);

    // Do the same for organizations.
    this.organizationsJaxbContext = JAXBContext.newInstance(jaxbOrgContextString);
    File organizationsFile = new File(cwd + orgXml);
    unmarshaller = this.organizationsJaxbContext.createUnmarshaller();
    this.organizations = (Organizations) unmarshaller.unmarshal(organizationsFile);

    // Now do it once more for the researchers.
    this.researchersJaxbContext = JAXBContext.newInstance(jaxbResearcherContextString);
    File researchersFile = new File(cwd + researcherXml);
    unmarshaller = this.researchersJaxbContext.createUnmarshaller();
    this.researchers = (Researchers) unmarshaller.unmarshal(researchersFile);
  }

  /**
   * Returns the number of Collaboration instances.
   * 
   * @return The number of collaborations.
   */
  public int getNumCollaborations() {
    return this.collaborations.getCollaboration().size();
  }

  /**
   * Returns the number of Organization instances.
   * 
   * @return The number of organizations.
   */
  public int getNumOrganizations() {
    return this.organizations.getOrganization().size();
  }

  /**
   * Returns the number of Researcher instances.
   * 
   * @return The number of researchers.
   */
  public int getNumResearchers() {
    return this.researchers.getResearcher().size();
  }
  
  /**
   * Returns the current Collaborations instance as a String encoding of its XML representation.
   * 
   * @return Its XML String representation.
   * @throws Exception If problems occur during translation.
   */
  public String getCollaborationsXml() throws Exception {
    Marshaller marshaller = this.collaborationsJaxbContext.createMarshaller();
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
    Document doc = documentBuilder.newDocument();
    marshaller.marshal(this.collaborations, doc);
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.transform(domSource, result); 
    String xmlString = writer.toString();
    return xmlString;
  }
  
  /**
   * Returns the current Collaborations instance as a String encoding of its XML representation.
   * 
   * @return Its XML String representation.
   * @throws Exception If problems occur during translation.
   */
  public String getOrganizationsXml() throws Exception {
    Marshaller marshaller = this.organizationsJaxbContext.createMarshaller();
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
    Document doc = documentBuilder.newDocument();
    marshaller.marshal(this.organizations, doc);
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.transform(domSource, result);
    String xmlString = writer.toString();
    return xmlString;
  }
  
  /**
   * Returns the current Collaborations instance as a String encoding of its XML representation.
   * 
   * @return Its XML String representation.
   * @throws Exception If problems occur during translation.
   */
  public String getReasearchersXml() throws Exception {
    Marshaller marshaller = this.researchersJaxbContext.createMarshaller();
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setNamespaceAware(true);
    DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
    Document doc = documentBuilder.newDocument();
    marshaller.marshal(this.researchers, doc);
    DOMSource domSource = new DOMSource(doc);
    StringWriter writer = new StringWriter();
    StreamResult result = new StreamResult(writer);
    TransformerFactory tf = TransformerFactory.newInstance();
    Transformer transformer = tf.newTransformer();
    transformer.transform(domSource, result);
    String xmlString = writer.toString();
    return xmlString;
  }
  
  /**
   * Marshalls the newly edited Researchers into XML format.
   * 
   * @param filePath Path to the existing XML file.
   * @return 0 if the file could not be open, 1 if file was found. 
   * @throws Exception If problems occur during translation.
   */
  public int marshallResearchers(String filePath) throws Exception {
    //String xmlResearchers = MyIsernXml.xmlLoader.getReasearchersXml();
  
    String xmlResearchers = getReasearchersXml();
    PrintWriter result;
      
    try {  
      result = new PrintWriter(new FileWriter(filePath));
    }
    catch (IOException e) {
       System.out.println("Can't open file: " + filePath);
       System.out.println(e.toString());
       return 0;     
    }
    result.flush();
    result.write(xmlResearchers);
    result.close();
    return 1;
  }
  
  /**
   * Marshalls the newly edited Organizations into XML format.
   * 
   * @param filePath Path to the existing XML file.
   * @return 0 if the file could not be open, 1 if file was found. 
   * @throws Exception If problems occur during translation.
   */
  public int marshallOrganizations(String filePath) throws Exception {
    //String xmlOrganizations = MyIsernXml.xmlLoader.getOrganizationsXml();       
    String xmlOrganizations = getOrganizationsXml();
    PrintWriter result;
      
    try {  
      result = new PrintWriter(new FileWriter(filePath));
    }
    catch (IOException e) {
       System.out.println("Can't open file: " + filePath);
       System.out.println(e.toString());
       return 0;     
    }
    result.flush();
    result.write(xmlOrganizations);
    result.close();
    return 1;
  }
  
  /**
   * Marshalls the newly edited Collaboration into XML format.
   * 
   * @param filePath Path to the existing XML file.
   * @return 0 if the file could not be open, 1 if file was found. 
   * @throws Exception If problems occur during translation.
   */
  public int marshallCollaborations(String filePath) throws Exception {
    //String xmlCollaborations = MyIsernXml.xmlLoader.getCollaborationsXml();
    String xmlCollaborations = getCollaborationsXml();
    PrintWriter result;
      
    try {  
      result = new PrintWriter(new FileWriter(filePath));
    }
    catch (IOException e) {
       System.out.println("Can't open file: " + filePath);
       System.out.println(e.toString());
       return 0;     
    }
    result.flush();
    result.write(xmlCollaborations);
    result.close();
    return 1;
  }
}
